package main

import (
	"fmt"
	"sync"
)

/*
*
我们之前介绍 goroutine 的时候介绍过，如果主 goroutine 运行结束，那么所有的协程将陪葬。
如果我们要等创建的协程运行完的话，之前的方法是让主 goroutine “sleep()” 一会儿，但是 sleep() 是要指定时间的，
而我们往往不能准确预估协程需要多长时间能运行完。所以用这个方法其实很笨拙。
现在我们有了 sync.WaitGroup 就方便太多啦！用 wg.Wait() 在主 goroutine 里等着，等所有 goroutine 全部运行完就直接返回。nice！

Go语言中除了可以使用通道（channel）和互斥锁进行两个并发程序间的同步外，还可以使用等待组进行多个任务的同步，等待组可以保证在并发环境中 完成指定数量的任务。

官方文档对 WaitGroup 的描述是：一个 WaitGroup 对象可以等待一组协程结束。使用方法是：

	main协程通过调用 wg.Add(delta int) 设置 worker 协程的个数，然后创建 worker 协程；
	worker协程执行结束以后，都要调用 wg.Done()；
	main协程调用 wg.Wait() 且被block，直到所有worker协程全部执行结束后返回。

三个方法：
func (wg *WaitGroup) Add(delta int)   //Add函数主要为WaitGroup的等待数+1或者+n
func (wg *WaitGroup) Done()           //Done函数调用的也是Add函数，主要用于-1操作
func (wg *WaitGroup) Wait()           //Wait函数是指阻塞当前协程，直到等待数归为0才继续向下执行
源码结构体

	type WaitGroup struct {
	  noCopy noCopy
	  state1 [3]uint32
	}

一个注意：
需要注意 sync.WaitGroup 是一个结构体，传递的时候要传递指针。
waitGroup 对象不是一个引用类型，在通过函数传值的时候，需要使用地址。
*/
func main() {
	wg := sync.WaitGroup{}
	wg.Add(100)
	for i := 0; i < 100; i++ {
		go func(i int) {
			fmt.Println(i)
			wg.Done()
		}(i)
	}
	wg.Wait()
}
